home *** CD-ROM | disk | FTP | other *** search
/ Univers Interactif 3 / INTERACTIF.BIN / mac / Planete.net / Internet Confirmés_Vrac / NetAgent.sea / src / server.c < prev    next >
Text File  |  1992-06-15  |  15KB  |  562 lines

  1. /*
  2. This is an unsupported product. It was developed as part of a study at Ostfold
  3. Regional College, Norway in the spring of 1992.
  4.  
  5. You use this software at your own risk. Neither the authors nor the Ostfold
  6. Regional College nor any other person or organization except yourself is
  7. responsible for any damage or loss of data derived from the use of this
  8. software. You may distribute this software freely as long as it is in its
  9. original form and all of its files are included. If you make any changes to any
  10. part of this software or the files distributed with it, please state so and do
  11. NOT distribute it under its original name.
  12. */
  13.  
  14. #include <stdio.h>
  15. #include <string.h>
  16. #include <sys/types.h>
  17. #include <sys/socket.h>
  18. #include <netinet/in.h>
  19. #include <netdb.h>
  20. #include <fcntl.h>
  21. #include "nntp_tcp.h"
  22. #include "div_func.h"
  23.  
  24. #define MAXLEN        4    
  25. #define NO_OF_WORDS    4
  26. #define NO_OF_KOMS    7    
  27.  
  28. #define QUIT        0    /* Quits */
  29. #define HELP        1    /* Sends help */
  30. #define USER        2    /* Adds/verifies user */
  31. #define RETV        3    /* Sends articles */
  32. #define NWRD        4    /* Add a subject */
  33. #define NWDS        5    /* Sets all subjects */
  34. #define NNWS        6    /* Tells if new news has arrived */
  35.  
  36.  
  37. typedef struct kommando {
  38.     char ord[NO_OF_WORDS][BUFSIZ+1];
  39.     int  type;
  40. }KOMMANDO;
  41.  
  42.  
  43. char koms[NO_OF_KOMS][MAXLEN+1] = {
  44.     "quit",
  45.     "help",
  46.     "user",
  47.     "retv",
  48.     "nwrd",
  49.     "nwds",
  50.     "nnws"
  51. };
  52.  
  53. int user_ok = 0;
  54. char usernavn[BUFSIZ+1];
  55.  
  56. /*
  57. -----------------------------------------------------------------------------
  58. Function name: parse_msg()
  59. -----------------------------------------------------------------------------
  60. Parameters:    char *s        The string to parse.
  61. Return value:    Returns a struct of type KOMMANDO. If the command is not
  62.         recognized the structs type is set to -1.
  63. Called by:    do_server()
  64. Calls:        none
  65. Description:    Checks if the string s is a server command or not. If it is,
  66.         then it return it in a KOMMANDO struct.
  67. -----------------------------------------------------------------------------
  68. */
  69.  
  70. KOMMANDO parse_msg(s)
  71. char *s;
  72. {
  73.     int x = 0, y = 0, t;
  74.     KOMMANDO k;
  75.  
  76.     k.type = -1;
  77.  
  78.     while( *s != '\0' && x < NO_OF_WORDS ) {
  79.         if( *s != 32 )
  80.             k.ord[x][y++] = *s;
  81.         else {
  82.             k.ord[x][y] = '\0';
  83.             y = 0;
  84.             x++;
  85.         }
  86.         s++;
  87.     }
  88.  
  89.     k.ord[x][y] = '\0';
  90.         y = 0;
  91.         x++;
  92.  
  93.  
  94.     while( x < NO_OF_WORDS )
  95.         k.ord[x++][0] = '\0';
  96.  
  97.  
  98.     for( t = 0; t < NO_OF_KOMS; t++) {
  99.         if( stricmp(&k.ord[0][0], &koms[t][0]) == 0 )
  100.             k.type = t;
  101.     }
  102.  
  103.     return(k);
  104. }
  105.  
  106. /*
  107. -----------------------------------------------------------------------------
  108. Function name: fjern_forste()
  109. -----------------------------------------------------------------------------
  110. Parameters:    char **s    Pointer to a pointer to a string.
  111. Return value:    none
  112. Called by:    none
  113. Calls:        none
  114. Description:    Removes the first character in a string.
  115. -----------------------------------------------------------------------------
  116. */
  117.  
  118. void fjern_forste(s)
  119. char **s;
  120. {
  121.     *s++;
  122. }
  123.  
  124. /*
  125. -----------------------------------------------------------------------------
  126. Function name: reg_user()
  127. -----------------------------------------------------------------------------
  128. Parameters:    int s        A valid socket
  129.         KOMMANDO k    A KOMMANDO struct
  130. Return value:    none
  131. Called by:    do_server()
  132. Calls:        tcp_send(), lock_file(), unlock_file(), les_linje()
  133. Description:    This function registrates a user or checks wether the user
  134.         exists or not. It uses the KOMMANDO struct to see if the user
  135.         exists, if not it initializes all of the files and makes a
  136.         directory for that user. It also updates the agent.users file
  137.         if it needs to. If the syntax of the command is wrong it
  138.         sends out an error message.
  139. -----------------------------------------------------------------------------
  140. */
  141.  
  142. void reg_user(s, k)
  143. int s;
  144. KOMMANDO k;
  145. {
  146.     int f;
  147.     char buf[BUFSIZ+1];
  148.     char user[BUFSIZ+1];
  149.     char buf2[BUFSIZ+1];
  150.     char innleggsfil[BUFSIZ+1];
  151.  
  152.     if( (k.ord[1][0] == '\0') || (k.ord[2][0] == '\0')) {
  153.         tcp_send(s, "451 usage: user name passwd\n");
  154.         return;
  155.     }
  156.  
  157.     if((f = open("agent.users", O_CREAT|O_RDWR, S_IREAD|S_IWRITE)) == -1) {
  158.         tcp_send(s, "503 server error\n");
  159.         return;
  160.     }
  161.  
  162.     lock_file(f);
  163.  
  164.     sprintf(user, "%s %s", &k.ord[1][0], &k.ord[2][0]);
  165.     
  166.     while(les_linje( f, buf)) {
  167.         if(stricmp(user, buf) == 0) {
  168.             strcpy(usernavn, &k.ord[1][0]);
  169.             user_ok = 1;
  170.             tcp_send(s, "250 user ok\n");
  171.             unlock_file(f);
  172.             close(f);
  173.             return;
  174.         }
  175.         else {
  176.             first_word(buf);
  177.             if(stricmp(buf,&k.ord[1][0]) == 0) {
  178.                 tcp_send(s, "444455 user login incorrect\n");
  179.                 unlock_file(f);
  180.                 close(f);
  181.                 return;
  182.             }
  183.         }
  184.     }
  185.  
  186.     sprintf(user, "%s\n", user);
  187.     if(write(f, user, strlen(user)) == -1) {
  188.         tcp_send(s, "503 server error\n");
  189.         return;
  190.     }
  191.     unlock_file(f);
  192.     close(f);
  193.  
  194.     if(mkdir(&k.ord[1][0], 511) != 0 ) {
  195.                 tcp_send(s, "503 server error\n");
  196.                 perror("mkdir");
  197.                 return;
  198.         }
  199.  
  200.     sprintf(innleggsfil, "%s/%s.subjects", &k.ord[1][0], &k.ord[1][0]);
  201.     if((f = open(innleggsfil, O_CREAT|O_RDWR, S_IREAD|S_IWRITE)) == -1) {
  202.                 tcp_send(s, "503 server error\n");
  203.                 return;
  204.         }
  205.     lock_file(f);
  206.     unlock_file(f);
  207.     close(f);
  208.  
  209.     strcpy(usernavn, &k.ord[1][0]);
  210.     user_ok = 1;
  211.         tcp_send(s, "252 new user ok\n");
  212.  
  213. }
  214.  
  215. /*
  216. -----------------------------------------------------------------------------
  217. Function name:    help()
  218. -----------------------------------------------------------------------------
  219. Parameters:    int s        A valid socket.
  220. Return value:    none
  221. Called by:    do_server()
  222. Calls:        tcp_send()
  223. Description:    Gives a respond to the HELP command. It sends all the data
  224.         to s.
  225. -----------------------------------------------------------------------------
  226. */
  227.  
  228. void help(s)
  229. int s;
  230. {
  231.     tcp_send(s, "202 help requested, help follows\n");
  232.         tcp_send(s, "NetAgent deamon version 0.9\n");
  233.         tcp_send(s, "Written by the NetAgent Project at Ostfold Regional College 1992\n");
  234.         tcp_send(s, "    (Per H. Johansen, Nina B. Olsen, Morten Kristiansen)\n");
  235.         tcp_send(s, "----------------------------------------------------------------\n");
  236.         tcp_send(s, "The server supports the following commands:\n");
  237.         tcp_send(s, "    USER    RETV    QUIT    NWRD\n");
  238.         tcp_send(s, "    HELP    NWDS    NNWS\n");
  239.         tcp_send(s, ".\n");
  240.  
  241. }
  242.  
  243. /*
  244. -----------------------------------------------------------------------------
  245. Function name: send_command_error()
  246. -----------------------------------------------------------------------------
  247. Parameters:    int s        A valid socket
  248. Return value:    none
  249. Called by:    none
  250. Calls:        tcp_send()
  251. Description:    Sends an error message to s if a command is not implemented.
  252. -----------------------------------------------------------------------------
  253. */
  254.  
  255. void send_command_error(s)
  256. int s;
  257. {
  258.     tcp_send(s,"501 command not implemented\n");
  259. }
  260.  
  261. /*
  262. -----------------------------------------------------------------------------
  263. Function name: send_user_error()
  264. -----------------------------------------------------------------------------
  265. Parameters:    int s        A valid socket
  266. Return value:    none
  267. Called by:    do_server()
  268. Calls:        tcp_send()
  269. Description:    Sends out an error message if someone gives it a command
  270.         which is user dependent and no user is logged in.
  271. -----------------------------------------------------------------------------
  272. */
  273.  
  274. void send_user_error(s)
  275. int s;
  276. {
  277.     tcp_send(s,"452 no user logged in\n");
  278. }
  279.  
  280. /*
  281. -----------------------------------------------------------------------------
  282. Function name: nytt_ord()
  283. -----------------------------------------------------------------------------
  284. Parameters:    int s        A valid socket.
  285.         char *t        pointer to a string.
  286. Return value:    none
  287. Called by:    do_server()
  288. Calls:        tcp_send(), lock_file(), unlock_file()
  289. Description:    This function add a new subject to the users <user>.subjects
  290.         file. The subject to be added is pointed to by t.
  291. -----------------------------------------------------------------------------
  292. */
  293.  
  294. void nytt_ord(s, t)
  295. int s;
  296. char *t;
  297. {
  298.     char fil[BUFSIZ+1];
  299.     char stikkord[BUFSIZ+1];
  300.     int f;
  301.  
  302.  
  303.     if( *t == '\0') {
  304.                 tcp_send(s, "454 usage: nwrd word\n");
  305.                 return;
  306.         }
  307.  
  308.     sprintf(fil, "%s/%s.subjects", usernavn, usernavn);
  309.  
  310.         if((f = open(fil, O_CREAT|O_RDWR|O_APPEND, S_IREAD|S_IWRITE)) == -1) {
  311.                 tcp_send(s, "503 server error\n");
  312.                 return;
  313.         }
  314.     lock_file(f);
  315.     sprintf(stikkord, "%s\n", t);
  316.  
  317.     if(write(f, stikkord, strlen(stikkord)) == -1) {
  318.                 tcp_send(s, "503 server error\n");
  319.                 return;
  320.         }
  321.     unlock_file(f);
  322.     close(f);
  323.  
  324.     tcp_send(s, "254 word added to list\n");
  325.  
  326. }
  327.  
  328. /*
  329. -----------------------------------------------------------------------------
  330. Function name:    nytt()
  331. -----------------------------------------------------------------------------
  332. Parameters:    int s        A valid socket.
  333. Return value:    none
  334. Called by:    do_server()
  335. Calls:        tcp_send(), lock_file(), unlock_file(), les_linje
  336. Description:    This function send the contents of the file <user>.articles
  337.         to the socket s. The transmission is ended with a '.'.
  338. -----------------------------------------------------------------------------
  339. */
  340.  
  341. void nytt(s)
  342. int s;
  343. {
  344.     char buf[BUFSIZ+1];
  345.     char command[BUFSIZ+1];
  346.     char fil[BUFSIZ+1];
  347.     int f;
  348.     
  349.     sprintf(fil, "%s/%s.articles", usernavn, usernavn);
  350.  
  351.         if((f = open(fil, O_CREAT|O_RDONLY|O_APPEND, S_IREAD|S_IWRITE)) == -1) {
  352.                 tcp_send(s, "503 server error\n");
  353.                 return;
  354.         }
  355.     lock_file(f);
  356.     tcp_send(s, "230 new news follows\n");
  357.  
  358.     while(les_linje(f, buf)) {
  359.         sprintf(command, "%s\n", buf);
  360.         tcp_send(s, command);
  361.     }
  362.     tcp_send(s, ".\n");
  363.     unlock_file(f);
  364.     close(f);
  365.  
  366.     if((f = open(fil, O_CREAT|O_WRONLY|O_TRUNC)) == -1) {
  367.                 tcp_send(s, "503 server error\n");
  368.                 return;
  369.         }
  370.     lock_file(f);
  371.     unlock_file(f);
  372.     close(f);
  373.  
  374.         sprintf(fil, "%s/%s.newnews", usernavn, usernavn);
  375.  
  376.         if((f=open(fil, O_CREAT|O_RDWR|O_TRUNC, S_IREAD|S_IWRITE)) == -1 ){
  377.                 tcp_send(s, "503 server error\n");
  378.                 return;
  379.         }
  380.     lock_file(f);
  381.  
  382.         write(f, "NO\n", 3);
  383.     unlock_file(f);
  384.         close(f);
  385.  
  386. }
  387.  
  388. /*
  389. -----------------------------------------------------------------------------
  390. Function name: new_words()
  391. -----------------------------------------------------------------------------
  392. Parameters:    int s        A valid socket
  393. Return value:    none
  394. Called by:    do_server()
  395. Calls:        tcp_send(), lock_file(), unlock_file(), get_list()
  396. Description:    This function recives a list of new subjects. The list must 
  397.         end with a '.'. The list is written to the <user>.subjects
  398.         file.
  399. -----------------------------------------------------------------------------
  400. */
  401.  
  402. void new_words(s)
  403. int s;
  404. {
  405.     int f;
  406.     char filnavn[BUFSIZ+1];
  407.     
  408.     tcp_send(s, "256 send new keywords\n");
  409.  
  410.     sprintf(filnavn, "%s/%s.subjects", usernavn, usernavn);
  411.     if((f = open(filnavn, O_CREAT|O_WRONLY|O_TRUNC, S_IREAD|S_IWRITE)) == -1) {
  412.         tcp_send(s, "503 server error\n");
  413.         return;
  414.     }
  415.     lock_file(f);
  416.     get_list(s, f, 3600);
  417.     unlock_file(f);
  418.     close(f);
  419. }
  420.  
  421. /*
  422. -----------------------------------------------------------------------------
  423. Function name: new_news()
  424. -----------------------------------------------------------------------------
  425. Parameters:    int s         A valid socket
  426. Return value:    none
  427. Called by:    do_server()
  428. Calls:        tcp_send(), lock_file(), unlock_file(), les_linje()
  429. Description:    This function sends a response which says if the user has new
  430.         news waiting. It reads the status from the <user>.newnews
  431.         file.
  432. -----------------------------------------------------------------------------
  433. */
  434.  
  435. void new_news(s)
  436. int s;
  437. {
  438.     char buf[BUFSIZ+1];
  439.     char fil[BUFSIZ+1];
  440.     int f;
  441.  
  442.     sprintf(fil, "%s/%s.newnews", usernavn, usernavn);
  443.  
  444.     if((f=open(fil, O_CREAT|O_RDONLY, S_IREAD|S_IWRITE)) == -1 ){
  445.         tcp_send(s, "503 server error\n");
  446.         return;
  447.     }
  448.     lock_file(f);
  449.  
  450.     if (les_linje(f, buf) <= 0) {
  451.         tcp_send(s, "456 no new news\n");
  452.         return;
  453.     }
  454.  
  455.     if( stricmp(buf, "YES") == 0)
  456.         tcp_send(s, "270 new news\n");
  457.     else
  458.         tcp_send(s, "456 no new news\n");
  459.     unlock_file(f);
  460.     close(f);
  461.     
  462.     if((f=open(fil, O_CREAT|O_RDWR|O_TRUNC, S_IREAD|S_IWRITE)) == -1 ){
  463.                 tcp_send(s, "503 server error\n");
  464.                 return;
  465.         }
  466.     lock_file(f);
  467.     
  468.     write(f, "NO\n", 3);
  469.     unlock_file(f);
  470.     close(f);
  471. }
  472.  
  473. /*
  474. -----------------------------------------------------------------------------
  475. Function name: do_server()
  476. -----------------------------------------------------------------------------
  477. Parameters:    int s        A valid socket
  478. Return value:    none
  479. Called by:    main() (agentd)
  480. Calls:        tcp_send(), recv_upto(), help(), reg_user(),
  481.         send_user_error(), nytt(), nytt_ord(), new_words(), 
  482.         new_news(), parse_msg()
  483. Description:    This is the core function of the server. It handles all
  484.         incomming commands and distributes them to the correct
  485.         functions.
  486. -----------------------------------------------------------------------------
  487. */
  488.  
  489. void do_server(s)
  490. int s;
  491. {
  492.     char command[BUFSIZ+1];
  493.     char localhost[33];
  494.     char *buf;
  495.     char melding[BUFSIZ+1];
  496.     int  slutt = 0;
  497.     KOMMANDO k;
  498.  
  499.     gethostname(localhost, 32);
  500.     sprintf(command, "200 NetAgent deamon(%s) version 0.9 ready.\n", localhost);    
  501.     tcp_send(s, command);
  502.     
  503.     melding[0] = '\0';    
  504.     k.type = -2;
  505.  
  506.     while(!slutt) {
  507.         if(recv_upto(s, RETURN, melding, 3600) <= 0) {
  508.             tcp_send(s, "505 error or timeout - closing\n");
  509.             close(s);
  510.             exit(1);
  511.         }
  512.         buf = melding;
  513.         if(*buf == LINEFEED)
  514.             buf++;
  515.         k = parse_msg(buf);
  516.         switch(k.type) {
  517.             case QUIT:
  518.                     tcp_send(s, "205 closing connection - goodbye\r\n");
  519.                     slutt = 1;
  520.                     break;
  521.             case HELP:
  522.                     help(s);
  523.                     break;
  524.             case USER:
  525.                     reg_user(s, k);
  526.                     break;
  527.             case RETV:
  528.                     if(user_ok)
  529.                         nytt(s);
  530.                                      else
  531.                         send_user_error(s); 
  532.                           break;
  533.             case NWRD:
  534.                     if(user_ok)
  535.                                                 nytt_ord(s, &k.ord[1][0]);
  536.                                         else
  537.                                                 send_user_error(s);
  538.                                         break;
  539.             case NWDS:
  540.                     if(user_ok)
  541.                                                 new_words(s);
  542.                                         else
  543.                                                 send_user_error(s);
  544.                                         break;
  545.             case NNWS:
  546.                     if(user_ok)
  547.                                                 new_news(s);
  548.                                         else
  549.                                                 send_user_error(s);
  550.                                         break;
  551.             default:
  552.                     tcp_send(s, "500 command not recognized\r\n");
  553.                     break;
  554.         }    
  555.     }
  556.     close(s);
  557.     exit(0);
  558.  
  559. }
  560.  
  561.  
  562.